package com.gitee.wsl.doc.prosemirror.plugin.writer

import com.gitee.wsl.doc.prosemirror.model.mark.Mark
import com.gitee.wsl.doc.prosemirror.model.node.Node

/**
 * Markdown序列化状态类
 * 用于跟踪状态并暴露与markdown序列化相关的方法
 */
class MarkdownSerializerState(
    val nodes: Map<String, NodeSerializer>,
    val marks: Map<String, MarkSerializerSpec>,
    val options: MarkdownSerializerOptions
) {
    var delim: String = ""
    var out: String = ""
    var closed: Node? = null
    var inAutolink: Boolean? = null
    var atBlockStart: Boolean = false
    var inTightList: Boolean = false

    init {
        // 初始化紧致列表状态
        this.inTightList = options.tightLists
    }

    /**
     * 刷新关闭状态
     */
    fun flushClose(size: Int = 2) {
        val closedNode = closed ?: return

        if (!atBlank()) {
            out += "\n"
        }

        if (size > 1) {
            var delimMin = delim
            val trim = Regex("\\s+$").find(delimMin)
            if (trim != null) {
                delimMin = delimMin.substring(0, delimMin.length - trim.value.length)
            }
            for (i in 1 until size) {
                out += "$delimMin\n"
            }
        }
        closed = null
    }

    /**
     * 获取标记信息
     */
    fun getMark(name: String): MarkSerializerSpec {
        val info = marks[name]
        if (info == null) {
            if (options.strict) {
                throw IllegalArgumentException("Mark type `$name` not supported by Markdown renderer")
            }
            return MarkSerializerSpec.blankMark
        }
        return info
    }

    /**
     * 渲染块内容
     */
    fun wrapBlock(delim: String, firstDelim: String?, node: Node, f: () -> Unit) {
        val old = this.delim
        write(if (firstDelim != null) firstDelim else delim)
        this.delim += delim
        f()
        this.delim = old
        closeBlock(node)
    }

    /**
     * 检查是否在空白处
     */
    fun atBlank(): Boolean {
        return Regex("(^|\\n)$").containsMatchIn(out)
    }

    /**
     * 确保内容以换行符结尾
     */
    fun ensureNewLine() {
        if (!atBlank()) out += "\n"
    }

    /**
     * 准备状态并写入输出
     */
    fun write(content: String? = null) {
        flushClose()
        if (delim.isNotEmpty() && atBlank()) {
            out += delim
        }
        if (content != null) {
            out += content
        }
    }

    /**
     * 关闭给定节点的块
     */
    fun closeBlock(node: Node) {
        closed = node
    }

    /**
     * 添加文本到文档
     */
    fun text(text: String, escape: Boolean = true) {
        val lines = text.split("\n")
        for (i in lines.indices) {
            write()

            // 在链接前转义感叹号
            if (!escape && lines[i].startsWith("[") && Regex("(^|[^\\\\])\\!$").containsMatchIn(out)) {
                out = out.substring(0, out.length - 1) + "\\!"
            }
            out += if (escape) esc(lines[i], atBlockStart) else lines[i]
            if (i != lines.size - 1) out += "\n"
        }
    }

    /**
     * 渲染给定节点作为块
     */
    fun render(node: Node, parent: Node, index: Int) {
        val serializer = nodes[node.type.name]
        if (serializer != null) {
            serializer(this, node, parent, index)
        } else {
            if (options.strict) {
                throw IllegalArgumentException("Token type `${node.type.name}` not supported by Markdown renderer")
            } else if (!node.type.isLeaf) {
                if (node.type.inlineContent) renderInline(node)
                else renderContent(node)
                if (node.type.isBlock) closeBlock(node)
            }
        }
    }

    /**
     * 渲染父节点的内容作为块节点
     */
    fun renderContent(parent: Node) {
        parent.forEach { node, _, index ->
            render(node, parent, index)
        }
    }

    /**
     * 渲染父节点的内容作为内联内容
     */
    fun renderInline(parent: Node, fromBlockStart: Boolean = true) {
        this.atBlockStart = fromBlockStart
        val active = mutableListOf<Mark>()
        var trailing = ""

        val progress = { node: Node?, offset: Int, index: Int ->
            val marks = node?.marks ?: emptyList()

            // 从硬换行中移除标记，防止解析器边界情况
            if (node != null && node.type.name == options.hardBreakNodeName) {
                marks.filter { mark ->
                    if (index + 1 == parent.childCount) false
                    else {
                        val next = parent.child(index + 1)
                        mark.isInSet(next.marks) && (!next.isText || Regex("\\S").containsMatchIn(next.text ?: ""))
                    }
                }
            }

            val leading = trailing
            trailing = ""
            // 这里需要实现完整的标记处理逻辑
            // 简化为直接渲染节点内容
            node?.let { render(it, parent, index) }
        }

        // 遍历所有子节点
        parent.children.forEachIndexed { index, node ->
            progress(node, 0, index)
        }
        progress(null, 0, parent.childCount)
    }

    /**
     * 转义字符串
     */
    fun esc(str: String, startOfLine: Boolean = false): String {
        var result = str
        // 基础转义规则
        val escapes = mapOf(
            "\\" to "\\\\",
            "`" to "\\`",
            "*" to "\\*",
            "_" to "\\_",
            "{" to "\\{",
            "}" to "\\}",
            "[" to "\\[",
            "]" to "\\]",
            "(" to "\\(",
            ")" to "\\)",
            "#" to "\\#",
            "+" to "\\+",
            "-" to "\\-",
            "." to "\\.",
            "!" to "\\!"
        )

        escapes.forEach { (char, escaped) ->
            result = result.replace(char, escaped)
        }

        // 行首特殊字符转义
        if (startOfLine) {
            val lineStartEscapes = mapOf(
                ">" to "\\>",
                "-" to "\\-",
                "=" to "\\=",
                "|" to "\\|",
                "." to "\\.",
                "+" to "\\+"
            )
            lineStartEscapes.forEach { (char, escaped) ->
                if (result.startsWith(char)) {
                    result = escaped + result.substring(1)
                }
            }
        }

        // 额外转义字符
        options.escapeExtraCharacters?.let { regex ->
            result = result.replace(regex, "\\\\$0")
        }

        return result
    }

    /**
     * 获取当前输出结果
     */
    fun getResult(): String = out
}


/**
 * 扩展函数：渲染块
 */
fun MarkdownSerializerState.renderBlock(node: Node, delim: String, f: () -> Unit) {
    wrapBlock(delim, null, node, f)
}



/**
 * 渲染列表
 */
fun MarkdownSerializerState.renderList(node: Node, delim: String, getDelim: (Int) -> String) {
    val oldTight = this.inTightList
    this.inTightList = true
    node.forEach { child, _, index ->
        if (index > 0) ensureNewLine()
        wrapBlock(delim, getDelim(index), child) {
            renderContent(child)
        }
    }
    this.inTightList = oldTight
}

